/**
 * @(#)AgrupacionK.java 30/10/06
 *
 * Copyright (c) 2005-2010 Psiqueware S.A. de C.V. All Rights Reserved.
 * This software is the proprietary information Psiqueware S.A. de C.V.
 * Use is subject to license terms.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * Usuario : Psique
 * Creaci&oacute;n: 30/10/05
 * Cambios :
 *  Fecha | Autor  |  Cambios
 * <ul>
 * <li> 30/10/05 | <a href = "mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a> | Creaci&oacute;n del Objeto.</li>
 * <li> 20/03/06 | <a href = "mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a> | Revisi&oacute;n, es renombrado de AgrupacionImp.</li>
 * <li>Feb 4, 2007 | <a href = "mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a> | Se cambio el RolSuperUsuario por un Rol Presidente.</li>
 * <li>Feb 5, 2007 | <a href = "mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a> | El Rol Presidente se cambio por Rol Raiz.</li>
 * </ul>
 */

package com.psiqueware.alheli.seguridad.modelo;

import com.psiqueware.alheli.basico.BaseObject;
import com.psiqueware.alheli.exception.NullArgumentException;
import com.psiqueware.alheli.seguridad.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Separa los Roles para un determinado AgrupacionK de Usuarios.
 * <br/>Paquete Original: com.psiqueware.basico.seguridad
 * <br/>Nombre  Original: AgrupacionK
 * <br/><a href="AgrupacionK.java.html"><i>Ver Fuente</i> </a>
 *
 * @author <a href="mailto:AngelElectrico@psiqueware.com">Angel El&eacute;ctrico</a>
 * @version Revision: 1.1 $ 30-oct-2005 13:39:28
 * @noinspection ClassWithoutLogger
 */
public final class AgrupacionK extends BaseObject implements Agrupacion
{

    /**
     * Lista de Roles para este {@link Agrupacion}
     */
    private final List<Rol> m_roles = new ArrayList<Rol>();

    /**
     * Identificador de la Credencial del UsuarioRaiz de esta Agrupacion.
     */
    private Long m_idCredencialUsuarioRaiz;

    /**
     * Listado de {@link Titulo}s que son propiedad del Presidente de la Agrupacion.
     */
    private List<Titulo> m_titulos = new ArrayList<Titulo>();


    /**
     * Construye una AgrupacionK.
     * <p>No requiere argumentos.</p>
     *
     * @noinspection ThisEscapedInObjectConstruction, CastToConcreteClass
     */
    public AgrupacionK()
    {

    }

    /**
     * A&ntilde;ade un Titulo al listado m_titulos, que son propiedad del Presidente de la Agrupacion.
     *
     * @param o {@link Titulo} a a&ntilde;adir.
     *
     * @return <tt>true</tt> (as per the general contract of the
     * <tt>Collection.add</tt> method).
     */
    public boolean addTitulo(Titulo o)
    {
        return m_titulos.add(o);
    }

    /**
     * Remueve un {@link Titulo} del listado {@code m_titulos}, que son propiedad del Presidente de la Agrupacion.
     *
     * @param o {@link Titulo} a eliminar.
     *
     * @return <tt>true</tt> if this list contained the specified element.
     */
    public boolean removeTitulo(Titulo o)
    {
        boolean salida = m_titulos.remove(o);

        return salida;

    }

    /**
     * Devuelve una copia del listado {@code m_titulos}, que son propiedad del Presidente de la Agrupacion.
     *
     * @return un nuevo ArrayList<Titulo>.
     */
    public List<Titulo> listTitulos()
    {
        List<Titulo> salida = new ArrayList<Titulo>(m_titulos);

        return salida;
    }

    /**
     * Devuelve la Lista de los {@link Titulo} que son propiedad del Presidente de la Agrupacion.
     *
     * @return List(unmodifiable) de 'm_titulos'. <code>null</code> en caso de no existir.
     *
     * @see java.util.List
     */
    public List<Titulo> getTitulos()
    {
        List<Titulo> salida = Collections.unmodifiableList(m_titulos);

        return salida;
    }

    /**
     * Establece la Lista de los {@link Titulo} que son propiedad del Presidente de la Agrupacion.
     *
     * @param newList nuevo valor para 'm_titulos'.
     *
     * @noinspection AssignmentToNull
     * @see java.util.List
     */
    public void setTitulos(List<? extends Titulo> newList)
    {
        this.m_titulos.clear();
        if (null != newList)
        {
            this.m_titulos = new ArrayList<Titulo>(newList);
        }
    }

    /**
     * Nos dice si el {@link Titulo} se encuentra contenido en la
     * lista.
     *
     * @param o {@link Titulo} a buscar.
     *
     * @return <code>true</code> si lo encuentra; <code>false</code> en caso contrario.
     */
    public boolean containsTitulo(Titulo o)
    {
        return m_titulos.contains(o);
    }

    /**
     * Buscamos los {@link Titulo}s de las {@link Propiedad}es dadas de alta con dicha clave. Lo devuelve solamente si el usuario es parte de esta {@link Agrupacion}.
     *
     * @param clave   de las propiedads cuyos {@link Titulo}s se buscan.
     * @param usuario que esta buscando el {@link Titulo}.
     *
     * @return List de {@link Titulo}s. En caso no existir algun {@link Titulo}, si el usuario esta autorizado una lista vacia; en caso contrario <code>null</code>.
     *
     * @noinspection CallToStringEquals
     */
    public List<Titulo> buscarTituloClavePropiedad(final String clave, UsuarioSeguridad usuario)
    {
        List<Titulo> salida = null;
        final Agrupacion agrupacion = usuario.getCredencial().getAgrupacion();
        if (this.equals(agrupacion))
        {
            salida = new ArrayList<Titulo>();
            for (Titulo titulo : m_titulos)
            {
                if (titulo.getClave().equalsIgnoreCase(clave))
                {
                    salida.add(titulo);
                }
            }
        }
        return salida;
    }

    /**
     * Nos dice si el {@link Rol} se encuentra contenido en la
     * lista.
     *
     * @param o {@link Rol} a buscar.
     */
    public boolean containsRol(Rol o)
    {
        return m_roles.contains(o);
    }

    /**
     * Convierte este {@link Agrupacion} a su representaci&oacute;n textual.
     *
     * @noinspection DuplicateStringLiteralInspection, MethodWithMultipleLoops
     */
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("<Instance Class = '").append(this.getClass()).append("'>");
        sb.append("<id>").append(m_id).append("</id>");
        sb.append("<roles>");
        for (Rol rol : m_roles)
        {
            sb.append("<rol>").append(rol.getNombre()).append("</rol>");
        }
        sb.append("</roles>");

        sb.append("</Instance>");
        return sb.toString();
    }

    @Override
    public boolean equals(final Object o)
    {
        if (this == o) return true;
        if (!(o instanceof AgrupacionK)) return false;
        if (!super.equals(o)) return false;

        final AgrupacionK that = (AgrupacionK) o;

        if (m_id != null ? !m_id.equals(that.m_id) : that.m_id != null)
            return false;
        if (m_idCredencialUsuarioRaiz != null ? !m_idCredencialUsuarioRaiz.equals(that.m_idCredencialUsuarioRaiz) : that.m_idCredencialUsuarioRaiz != null)
            return false;

        return true;
    }

    @Override
    public int hashCode()
    {
        int result = super.hashCode();
        result = 31 * result + (m_id != null ? m_id.hashCode() : 0);
        result = 31 * result + (m_idCredencialUsuarioRaiz != null ? m_idCredencialUsuarioRaiz.hashCode() : 0);
        return result;
    }

    /**
     * Devuelve una copia de la lista de {@link Rol} que act&uacute;an sobre este {@link Agrupacion}.
     */
    public List<Rol> listRoles()
    {
        return new ArrayList<Rol>(m_roles);
    }

    /**
     * A&ntilde;ade un {@link Rol} a esta {@link Agrupacion}.
     *
     * @param rol a agregar.
     *
     * @return <code>true</code> si se autoriz&oacute; a&ntilde;adir el {@link Rol}; <code>false</code> en caso contrario.
     */
    public void addRol(final Rol rol)
    {
        if (!m_roles.contains(rol)) m_roles.add(rol);
    }

    /**
     * Remueve un {@link Rol} de los asignados a esta {@link Credencial}.
     *
     * @param rol a eliminar.
     */
    public void removeRol(final Rol rol)
    {
        m_roles.remove(rol);
    }

    /**
     * Nos dice si el {@link Agrupacion} ya contiene este {@link Rol}.
     *
     * @param nombreRol cadena con el {@link Rol}.
     *
     * @return <code>true</code> si existe un {@link Rol} con el nombre dado en este {@link Agrupacion}; <code>false</code> en caso contrario.
     *
     * @noinspection CallToStringEquals
     */
    public boolean isRolRegistrado(String nombreRol)
    {
        boolean salida = false;
        for (Rol rol : m_roles)
        {
            if (rol.getNombre().equals(nombreRol))
            {
                salida = true;
                break;
            }
        }
        return salida;
    }

    /**
     * Devuelve el {@link Rol} de esta {@link Agrupacion} para el nombre dado.
     *
     * @param nombre cadena con el {@link Rol}.
     *
     * @return el {@link Rol} de ese nombre en caso de encontrarlo; <code>null</code> en caso contrario.
     *
     * @noinspection CallToStringEquals
     */
    public Rol buscaRolRegistrado(String nombre)
    {
        if (null == nombre)
            throw new NullArgumentException("<error>El argumento nombre del rol no puede ser NULL.</error>");

        Rol salida = null;
        for (Rol rol : m_roles)
        {
            if (rol.getNombre().equals(nombre))
            {
                salida = rol;
                break;
            }
        }
        return salida;
    }

    /**
     * Devuelve el Lista de Roles para este {@link Agrupacion}
     *
     * @return valor de 'roles'.
     *
     * @see List
     */
    public List<Rol> getRoles()
    {
        return new ArrayList<Rol>(m_roles);
    }

    /**
     * Establece el Lista de Roles para este {@link Agrupacion}
     *
     * @param roles nuevo valor para 'roles'.
     *
     * @noinspection AssignmentToNull
     * @see List
     */
    public void setRoles(List<Rol> roles)
    {
        this.m_roles.clear();
        if (null != roles)
        {
            m_roles.addAll(roles);
        }
    }

    /**
     * Devuelve el Identificador de la Credencial del UsuarioRaiz de esta Agrupacion.
     *
     * @return valor de 'idCredencialUsuarioRaiz'.
     */
    public Long getIdCredencialUsuarioRaiz()
    {
        return m_idCredencialUsuarioRaiz;
    }

    /**
     * Establece el Identificador de la Credencial del UsuarioRaiz de esta Agrupacion.
     *
     * @param idCredencialUsuarioRaiz nuevo valor para 'idCredencialUsuarioRaiz'.
     */
    public void setIdCredencialUsuarioRaiz(final Long idCredencialUsuarioRaiz)
    {
        m_idCredencialUsuarioRaiz = idCredencialUsuarioRaiz;
    }
}
